#include <iostream>
#include <functional>
#include <algorithm>
#include <time.h>


#include "log.h"
#include "config.h"
namespace sylar
{

struct LogAppenderDefine
{
    int type = 0;       //1 File, 2 Stdout
    LogLevel::Level level = LogLevel::UNKNOW;
    std::string formatter;      // 具体formatter格式
    std::string file;

    bool operator== (const LogAppenderDefine& oth) const
    {
        return type == oth.type
            && level == oth.level
            && formatter == oth.formatter
            && file == oth.file;
    }
};


struct LogDefine
{
    std::string name;
    LogLevel::Level level = LogLevel::Level::UNKNOW;
    std::string formatter;

    std::vector<LogAppenderDefine> appenders;

    bool operator==(const LogDefine& oth) const 
    {
        return name == oth.name
            && level == oth.level
            && formatter == oth.formatter
            && appenders == appenders;
    }

    bool operator < (const LogDefine& oth) const
    {
        return name < oth.name;
    }

};

template<>
class LexicalCast<std::string, LogDefine>
{
public:
    LogDefine operator()(const std::string& val)
    {
        YAML::Node node = YAML::Load(val);
        LogDefine result;

        if (!node["name"].IsDefined())
        {
            std::cout << "log config error: name is null, " << node
                      << std::endl;
                throw std::logic_error("log config name is null");
        }
        result.name = node["name"].as<std::string>();
        result.level = LogLevel::fromString(node["level"].IsDefined() ? node["level"].as<std::string>() : "");

        if (node["formatter"].IsDefined())
        {
            result.formatter = node["formatter"].as<std::string>();
        }

        if (node["appenders"].IsDefined())
        {
            for (size_t x = 0; x < node["appenders"].size(); x++)
            {
                auto a = node["appenders"][x];
                if (!a["type"].IsDefined())
                {
                    std::cout << "log config error: appender type is null, " << a
                              << std::endl;
                    continue;
                }
                LogAppenderDefine lad;
                std::string type = a["type"].as<std::string>();
                if ("FileLogAppender" == type)
                {
                    lad.type = 1;
                    if (!a["file"].IsDefined())
                    {
                        std::cout << "log config error: fileappender file is null, " << a
                              << std::endl;
                        continue;
                    }
                    lad.file = a["file"].as<std::string>();
                    if (a["formatter"].IsDefined())
                    {
                        lad.formatter  = a["formatter"].as<std::string>();
                    }
                }
                else if ("StdoutLogAppender" == type)
                {
                    lad.type = 2;
                    if (a["formatter"].IsDefined())
                    {
                        lad.formatter = a["formatter"].as<std::string>();
                    }
                }
                else
                {
                    std::cout << "log config error: appender type is invalid, " << a
                              << std::endl;
                    continue;
                }
                result.appenders.push_back(lad);
            }
        }

        return result;
    }


};

template<>
class LexicalCast<LogDefine, std::string>
{
public:

    std::string operator()(const LogDefine& val)
    {
        YAML::Node node;
        node["name"] = val.name;
        if (LogLevel::UNKNOW != val.level)
        {
            node["level"] = LogLevel::toString(val.level);
        }
        if (!val.formatter.empty())
        {
            node["formatter"] = val.formatter;
        }

        for (auto& a : val.appenders)
        {
            YAML::Node na;
            if (a.type == 1)
            {
                na["type"] = "FileLogAppender";
                na["file"] = a.file;
            }
            else if (a.type == 2)
            {
                na["type"] = "StdoutLogAppender";
            }

            if (LogLevel::UNKNOW != a.level)
            {
                na["level"] = LogLevel::toString(a.level);
            }

            if (!a.formatter.empty())
            {
                na["formatter"] = a.formatter;
            }

            node["appenders"].push_back(na);
        }
        std::stringstream ss;
        ss << node;
        return ss.str();
    }
};

sylar::ConfigVar<std::set<LogDefine> >::ptr g_log_defines = 
        sylar::Config::LookUp("logs", std::set<LogDefine>(), "logs config");

const char* LogLevel::toString(const sylar::LogLevel::Level& logLevel)
{   
    switch (logLevel)
    {
#define NAME_TO_STR(name)        \
    case Level::name:  \
    {                   \
        return #name;    \
        break;          \
    } 
    NAME_TO_STR(DEBUG)
    NAME_TO_STR(INFO)
    NAME_TO_STR(WARN)
    NAME_TO_STR(ERROR)
    NAME_TO_STR(FATAL)
#undef NAME_TO_STR
    default:
        return "UNKNOW_LEVEL";
        break;
    }
    return "UNKNOW_LEVEL";
}

const LogLevel::Level LogLevel::fromString(const std::string& strString)
{

#define FROM_STRING(level, val)      \
    if (strString == #val)          \
    {                               \
        return Level::level;        \
    }
    // 小写
    FROM_STRING(DEBUG, debug)
    FROM_STRING(INFO, info)
    FROM_STRING(WARN, warn)
    FROM_STRING(ERROR, error)
    FROM_STRING(FATAL, fatal)

    // 大写
    FROM_STRING(DEBUG, DEBUG)
    FROM_STRING(INFO, INFO)
    FROM_STRING(WARN, WARN)
    FROM_STRING(ERROR, ERROR)
    FROM_STRING(FATAL, FATAL)
    FROM_STRING(FATAL, FATAL)

    return Level::UNKNOW;
#undef FORM_STRING
}


LogEvent::LogEvent(std::shared_ptr<Logger> pLogger,
        LogLevel::Level logLevel, const char* cFileName, 
        uint32_t uiLine, uint64_t ulElapse, uint32_t uiTheadId,
        uint32_t uiFiberId, uint64_t ulTime, const std::string& strTheadName)
    : m_cFileName(cFileName)
    , m_uiLine(uiLine)
    , m_ulElapse(ulElapse)
    , m_uiThreadId(uiTheadId)
    , m_uiFiberId(uiFiberId)
    , m_ulTime(ulTime)
    , m_strTheadName(strTheadName)
    , m_pLogger(pLogger)
    , m_logLevel(logLevel)
    {

    }


void LogEvent::setFormat(const  char* fmt, ...)
{
    va_list al;
    va_start(al, fmt);
    setFormat(fmt, al);
    va_end(al);
}

void LogEvent::setFormat(const char* fmt, va_list al)
{
    char* cBuf = nullptr;
    int ilen = vasprintf(&cBuf, fmt, al);
    if (-1 != ilen)
    {
        m_ssLog << std::string(cBuf);
        free(cBuf);
    }
}

LogEventWrap::LogEventWrap(LogEvent::ptr pLogEvent)
    : m_pLogEvent(pLogEvent)
    {
        
    }


LogEventWrap::~LogEventWrap()
{   // 在这里调用 Appender 输出日志信息
    m_pLogEvent->getLogger()->Log(m_pLogEvent->getLogLevel(), m_pLogEvent);
}

std::stringstream& LogEventWrap::getSS()
{
    return m_pLogEvent->getSS();
}

LogFormatter::LogFormatter(const std::string& strPattern)
    : m_strPattern(strPattern) , m_isError(false)
{
    Init();
}

std::string LogFormatter::Format(std::shared_ptr<Logger> pLogger, LogLevel::Level logLevel, LogEvent::ptr pLogEvent)
{
    std::stringstream ss;
    for(auto& i : m_FormatItems)
    {
        i->Format(ss, pLogger, logLevel, pLogEvent);
    }
    return ss.str();
}

std::ostream& LogFormatter::Format(std::ostream& ofs, std::shared_ptr<Logger> pLogger, LogLevel::Level logLevel, LogEvent::ptr pLogEvent)
{
    for (auto& i : m_FormatItems)
    {
        i->Format(ofs, pLogger, logLevel, pLogEvent);
    }
    return ofs;
}


// 日志类型: 消息项
class MessageFormatItem : public LogFormatter::BaseLogFormatItem
{
public:
    MessageFormatItem(const std::string& str = "") {}
    void Format(std::ostream& os, std::shared_ptr<Logger> Logger, LogLevel::Level Level, LogEvent::ptr Event) override
    {
        os << Event->getContent();  // 返回日志内容
    }
};

// 日志类型: 日志级别
class LevelFormatItem : public LogFormatter::BaseLogFormatItem
{
public:
    LevelFormatItem(const std::string& str = "") {}
    void Format(std::ostream& os, std::shared_ptr<Logger> Logger, LogLevel::Level Level, LogEvent::ptr Event) override
    {
        os << LogLevel::toString(Level);
    }
};

// 毫秒数
class ElapseFormatItem : public LogFormatter::BaseLogFormatItem
{
public:
    ElapseFormatItem(const std::string& str = "") { }
    void Format(std::ostream& os, std::shared_ptr<Logger> Logger, LogLevel::Level Level, LogEvent::ptr Event) override
    {
        os << Event->getElapse();
    }
};

//日志名称
class NameFormatItem : public LogFormatter::BaseLogFormatItem
{
public:
    NameFormatItem(const std::string& str = "") {}
    void Format(std::ostream& os, std::shared_ptr<Logger> Logger, LogLevel::Level Level, LogEvent::ptr Event) override
    {
        os << Event->getLogger()->GetLogName();
    }
};

// 线程名称
class ThreadIdFormatItem : public LogFormatter::BaseLogFormatItem
{
public: 
    ThreadIdFormatItem(const std::string& str = "") {}
    void Format(std::ostream& os, std::shared_ptr<Logger> Logger, LogLevel::Level Level, LogEvent::ptr Event) override
    {
        os << Event->getTheadId();
    }

};

// 换行
class NewLineFormatItem : public LogFormatter::BaseLogFormatItem
{
public:
    NewLineFormatItem(const std::string& str = "") {}
    void Format(std::ostream& os, std::shared_ptr<Logger> Logger, LogLevel::Level Level, LogEvent::ptr Event) override
    {
        os << std::endl;
    }
};

// 日志内容
class StringLogFormatItem : public LogFormatter::BaseLogFormatItem
{
public:
    StringLogFormatItem(const std::string& str = "")
    : m_Log(str) { }

    void Format(std::ostream& os, std::shared_ptr<Logger> Logger, LogLevel::Level Level, LogEvent::ptr Event) override
    {
        os << this->m_Log;
    }
private:
    std::string m_Log;
};

// 制表符
class TableFormaItem : public LogFormatter::BaseLogFormatItem
{
public: 
    TableFormaItem (const std::string& str = "") {}

    void Format(std::ostream& os, std::shared_ptr<Logger> Logger, LogLevel::Level Level, LogEvent::ptr Event) override
    {
        os << "\t";
    }
};

// 携程id
class FiberIdFormatItem : public LogFormatter::BaseLogFormatItem
{
public:
    FiberIdFormatItem(const std::string& str = "") {}

    void Format(std::ostream& os, std::shared_ptr<Logger> Logger, LogLevel::Level Level, LogEvent::ptr Event) override
    {
        os << Event->getFiberId();
    }
};

// 线程名称
class ThreadNameFormatItem : public LogFormatter::BaseLogFormatItem
{
public:
    ThreadNameFormatItem(const std::string& str = "") {}
    
    void Format(std::ostream& os, std::shared_ptr<Logger> Logger, LogLevel::Level Level, LogEvent::ptr Event) override
    {
        os << Event->getTheadName();
    }
};

// 行号
class LineFormatItem : public LogFormatter::BaseLogFormatItem
{
public: 
    LineFormatItem(const std::string& str = "")
    {}

    void Format(std::ostream& os, std::shared_ptr<Logger> Logger, LogLevel::Level Level, LogEvent::ptr Event) override
    {
        os << Event->getLine();
    }
};

// 文件名称
class FilenameFormatItem : public LogFormatter::BaseLogFormatItem
{
public:
    FilenameFormatItem(const std::string& str = "") {}

    void Format(std::ostream& os, std::shared_ptr<Logger> Logger, LogLevel::Level Level, LogEvent::ptr Event) override
    {
        os << Event->getFileName();
    }
};

// 时间
class DateTimeFormatItem : public LogFormatter::BaseLogFormatItem
{
public: // 年-月-日 时:分:秒
    DateTimeFormatItem(const std::string& strFmt = "%Y-%d-%m %H:%M:%S")
    : m_strFmt(strFmt)
    {
        if (m_strFmt.empty())
        {
            m_strFmt = "%Y-%d-%m %H:%M:%S";
        }
    }

    void Format(std::ostream& os, std::shared_ptr<Logger> Logger, LogLevel::Level Level, LogEvent::ptr Event) override
    {
        struct tm timer;
        time_t time = Event->getTime();
        localtime_r(&time, &timer);
        //std::unique_ptr<char[]> pBuf = std::make_unique<char[]>(60);
        char buf[60] = {""};
        memset(buf, 0, sizeof(buf));
        strftime(buf, sizeof(buf), m_strFmt.c_str(), &timer);
        os << buf;
    }

private:
    std::string m_strFmt;
};


//%xxx %xxx{xxx} %%
void LogFormatter::Init()
{
    // m/t..., format, type（格式标记）
    using FORMAT_TYPE = std::string;
    using TYPE = int;
    std::vector<std::tuple<std::string, FORMAT_TYPE, TYPE>> vec;

    std::string nstr;   //保存解析常规后字符
    for(size_t i = 0; i < m_strPattern.size(); ++i) 
    {
        if ('%' != m_strPattern[i])
        {   // []
            nstr.append(1, m_strPattern[i]);
            continue;
        }

        if ((i + 1) < m_strPattern.size())
        {
            if ('%' == m_strPattern[i + 1])
            {   // %%: 两个% 转义%格式
                nstr.append(1, '%'); // 
                continue;
            }
        }

        size_t n = i + 1;
        int fmt_status = 0;     // 0  没有解析开始解析 {};  1 开始解析
        size_t fmt_begin = 0;

        std::string str;    // 保存 %d{%Y-%m-%d %H:%M:%S} 中 %Y-%m-%d %H:%M:%S 部分
        std::string fmt;
        while(n < m_strPattern.size()) 
        {

            if(!fmt_status && (!isalpha(m_strPattern[n]) && m_strPattern[n] != '{'
                    && m_strPattern[n] != '}')) 
            {
                str = m_strPattern.substr(i + 1, n - i - 1);
                break;
            }

            if(fmt_status == 0)
            {
                if(m_strPattern[n] == '{') 
                {
                    str = m_strPattern.substr(i + 1, n - i - 1);
                    //std::cout << "*" << str << std::endl;
                    fmt_status = 1; //解析格式
                    fmt_begin = n;
                    ++n;
                    continue;
                }
            } 
            else if(fmt_status == 1)
            {
                if(m_strPattern[n] == '}') 
                {
                    fmt = m_strPattern.substr(fmt_begin + 1, n - fmt_begin - 1);
                    //std::cout << "#" << fmt << std::endl;
                    fmt_status = 0;
                    ++n;
                    break;
                }
            }

            ++n;

            if(n == m_strPattern.size()) 
            {
                if(str.empty()) 
                {
                    str = m_strPattern.substr(i + 1);
                }
            }
        }

        if (0 == fmt_status)
        {
            if (!nstr.empty())
            {
                //vec.push_back(std::make_tuple(str, std::string(), 0));
                //  插入  [  or  ]
                vec.push_back(std::make_tuple(nstr, std::string(), 0));
                nstr.clear();
            } 
            vec.push_back(std::make_tuple(str, fmt, 1));
            i = n - 1;
        }
        else if(fmt_status == 1) 
        {
            std::cout << "pattern parse error: " << m_strPattern << " - " << m_strPattern.substr(i) << std::endl;
            m_isError = true;
            vec.push_back(std::make_tuple("<<pattern_error>>", fmt, 0));
        }
        else if (2 == fmt_status)
        {
            if (!nstr.empty())
            {
                vec.push_back(std::make_tuple(str, std::string(), 0));
                nstr.clear();
            }
            vec.push_back(std::make_tuple(str, fmt, 1));
            i = n;
        }

    }

    if(!nstr.empty()) 
    {
        vec.push_back(std::make_tuple(nstr, "", 0));
    }

    using LogFormatItemConstruct = std::function<BaseLogFormatItem::LogFormatItemPtr(const std::string&  str)>;
                            // lambda表达式:function<int(int)> = [](int){return int}
    // 格式: 消息类(多态)   BaseLogFormatItem::LogFormatItemPtr: 返回值,std::string&:参数
    static std::map<std::string, LogFormatItemConstruct> s_format_items{

 #define REGISE_LOGFORMAT(str, item) \
        {#str, [](const std::string& strFormat){ \
            return BaseLogFormatItem::LogFormatItemPtr(new item(strFormat)); }} \

        REGISE_LOGFORMAT(m, MessageFormatItem),           //m:消息
        REGISE_LOGFORMAT(p, LevelFormatItem),             //p:日志级别
        REGISE_LOGFORMAT(r, ElapseFormatItem),            //r:累计毫秒数
        REGISE_LOGFORMAT(c, NameFormatItem),              //c:日志名称
        REGISE_LOGFORMAT(t, ThreadIdFormatItem),          //t:线程id
        REGISE_LOGFORMAT(n, NewLineFormatItem),           //n:换行
        REGISE_LOGFORMAT(d, DateTimeFormatItem),          //d:时间
        REGISE_LOGFORMAT(f, FilenameFormatItem),          //f:文件名
        REGISE_LOGFORMAT(l, LineFormatItem),              //l:行号
        REGISE_LOGFORMAT(T, TableFormaItem),               //T:Tab
        REGISE_LOGFORMAT(F, FiberIdFormatItem),           //F:协程id
        REGISE_LOGFORMAT(N, ThreadNameFormatItem),        //N:线程名称

#undef REGISE_LOGFORMAT
    };

    for(auto& i : vec) 
    {
        if(std::get<2>(i) == 0) 
        {
            m_FormatItems.push_back(BaseLogFormatItem::LogFormatItemPtr(new StringLogFormatItem(std::get<0>(i))));
        } 
        else 
        {
            auto it = s_format_items.find(std::get<0>(i));
            if(it == s_format_items.end()) 
            {
                m_FormatItems.push_back(BaseLogFormatItem::LogFormatItemPtr(new StringLogFormatItem("<<error_format %" + std::get<0>(i) + ">>")));
                m_isError = true;
            } 
            else
            {
                m_FormatItems.push_back(it->second(std::get<1>(i)));
            }
        }

        //std::cout << "(" << std::get<0>(i) << ") - (" << std::get<1>(i) << ") - (" << std::get<2>(i) << ")" << std::endl;
    }
    // std::cout << m_FormatItems.size() << std::endl;

    
    // %m: 消息体。
    // %p：输出日志信息的优先级，即DEBUG，INFO，WARN，ERROR，FATAL。
    // %r：输出自应用程序启动到输出该log信息耗费的毫秒数。
    // %c：日志名称
    // %t: 线程id
    // %n: 回车换行
    // %d: 时间
    // %f: 文件名
    // %l: 行号
}


LogFormatter::LogFormatPtr BaseLogAppender::GetLogFormat()
{
    MutexType::Lock lock(m_mutex);
    return m_pLogFormat;
} 

void BaseLogAppender::SetLogFormat(LogFormatter::LogFormatPtr pLogFormat)
{
    MutexType::Lock lock(m_mutex);
    m_pLogFormat = pLogFormat;
    if (m_pLogFormat)
    {
        m_bHasFormat = true;
    }
    else
    {
        m_bHasFormat = false;
    }
}

void StdOutLogAppender::Log(std::shared_ptr<Logger> pLogger, LogLevel::Level logLevel, LogEvent::ptr pLogEvent)
{
    if (logLevel >= m_LogLevel)
    {
        MutexType::Lock lock(m_mutex);
        m_pLogFormat->Format(std::cout, pLogger, logLevel, pLogEvent);
    }
}

std::string StdOutLogAppender::ToYAMLString()
{
    MutexType::Lock lock(m_mutex);
    YAML::Node node;
    node["type"] = "StdOutLogAppender";
    if (LogLevel::UNKNOW != m_LogLevel)
    {
        node["level"] = LogLevel::toString(m_LogLevel);
    }
    if (m_bHasFormat && m_pLogFormat)
    {
        node["formatter"] = m_pLogFormat->GetPattern();
    }


    std::stringstream ss;
    ss << node;
    return ss.str();
}

FileOutLoggAppender::FileOutLoggAppender(std::string strFileName)
    : m_strFileName(strFileName)
{
    ReOpen();
}

void FileOutLoggAppender::Log(std::shared_ptr<Logger> pLogger, LogLevel::Level logLevel, LogEvent::ptr pLogEvent)
{
    if (logLevel >= m_LogLevel)
    {
        MutexType::Lock lock(m_mutex);
        uint64_t uiNow = pLogEvent->getTime();
        if (uiNow >= (m_ulLastOpenTime + 3))
        {
            ReOpen();
            m_ulLastOpenTime = uiNow;
        }
        if (!m_pLogFormat->Format(m_FileStream, pLogger, logLevel, pLogEvent))
        {
            std::cout << "error FileOutLoggAppender::Log" << std::endl; 
        }
    }

}

std::string FileOutLoggAppender::ToYAMLString()
{
    MutexType::Lock  lock(m_mutex);
    YAML::Node node;
    node["type"] = "FileOutLoggAppender";
    node["file"] = m_strFileName;
    if (m_LogLevel != LogLevel::UNKNOW)
    {
        node["level"] = LogLevel::toString(m_LogLevel);
    }

    if (m_bHasFormat && m_pLogFormat)
    {
        node["formatter"] = m_pLogFormat->GetPattern();
    }

    std::stringstream ss;
    ss << node;
    return ss.str();
}

bool FileOutLoggAppender::ReOpen()
{
    if (m_FileStream)
    {
        m_FileStream.close();   // 关闭
    }
    m_FileStream.open(m_strFileName, std::ios::app);
    return m_FileStream.is_open();
}

Logger::Logger(const std::string& strName)
    : m_strLoggerName(strName)
    , m_logLevel(LogLevel::DEBUG)
{
    m_pLogFormatter.reset(new LogFormatter("%d{%Y-%m-%d %H:%M:%S}%T%t%T%N%T%F%T[%p]%T[%c]%T%f:%l%T%m%n"));
}

void Logger::Log(LogLevel::Level logLevel, LogEvent::ptr plogEvent)
{
    if (logLevel >= m_logLevel)
    {
        auto pSelf = shared_from_this();
        MutexType::Lock  lock(m_mutex);
        if (!m_Appenders.empty())
        {
            for (auto i : m_Appenders)
            {
                i->Log(pSelf, logLevel, plogEvent);
            }
        }
        else if (m_Root)
        {   // 使用管理器的日志格式
            m_Root->Log(logLevel, plogEvent);
        }
    }
}

void Logger::Debug(LogEvent::ptr plogEvent)
{
   this->Log(LogLevel::DEBUG, plogEvent);
}
void Logger::Info(LogEvent::ptr plogEvent)
{
    this->Log(LogLevel::INFO, plogEvent);
}
void Logger::Error(LogEvent::ptr plogEvent)
{
    this->Log(LogLevel::ERROR, plogEvent);
}
void Logger::Warn(LogEvent::ptr plogEvent)
{
    this->Log(LogLevel::WARN, plogEvent);
}
void Logger::Fatal(LogEvent::ptr plogEvent)
{
    this->Log(LogLevel::FATAL, plogEvent);
}


void Logger::AddAppender(BaseLogAppender::LogAppenderPtr plogAppender)
{
    MutexType::Lock  lock(m_mutex);
    if (!plogAppender->GetLogFormat())
    {
        MutexType::Lock  lock(plogAppender->m_mutex);
        plogAppender->m_pLogFormat = m_pLogFormatter;
    }
    m_Appenders.push_back(plogAppender);
}

void Logger::DelAppender(BaseLogAppender::LogAppenderPtr plogAppender)
{
    for (auto ite = m_Appenders.begin(); ite != m_Appenders.end(); ++ite)
    {
        if (*ite == plogAppender)
        {
            m_Appenders.erase(ite);
        }
    }
}

void Logger::CleanAppender()
{
    m_Appenders.clear();
}

void Logger::SetFormmat(LogFormatter::LogFormatPtr plogFormmat)
{
    MutexType::Lock lock(m_mutex);
    m_pLogFormatter = plogFormmat;
    for (auto& i : m_Appenders)
    {
        MutexType::Lock  llock(i->m_mutex);
        if (!i->m_bHasFormat)
        {
            i->m_pLogFormat = plogFormmat;
        }
    }
}

void Logger::SetFormmat(const std::string& strFormmat)
{
    LogFormatter::LogFormatPtr new_format = std::make_shared<LogFormatter>(strFormmat);
    if (new_format->IsError())
    {
        std::cout << "Logger setFormatter name=" << m_strLoggerName
                  << " value=" << strFormmat << " invalid formatter"
                  << std::endl;
    }
    SetFormmat(new_format);
}

LogFormatter::LogFormatPtr Logger::GetFormmat()
{
    MutexType::Lock lock(m_mutex);
    return m_pLogFormatter;
}

std::string Logger::ToYmalString()
{
    MutexType::Lock  lock(m_mutex);
    YAML::Node node;
    node["name"] = m_strLoggerName;

    if (m_logLevel != LogLevel::UNKNOW)
    {
        node["level"] = LogLevel::toString(m_logLevel);
    }

    if (m_pLogFormatter)
    {
        node["formatter"] = m_pLogFormatter->GetPattern();
    }

    for (auto& i : m_Appenders)
    {
        node["appenders"].push_back(YAML::Load(i->ToYAMLString()));
    }

    std::stringstream ss;
    ss << node;
    return ss.str();
}


LoggerManager::LoggerManager()
{
    m_RootLogger.reset(new Logger);

    m_RootLogger->AddAppender(BaseLogAppender::LogAppenderPtr(new StdOutLogAppender));

    m_Loggers[m_RootLogger->m_strLoggerName] = m_RootLogger;
    Init();
}

Logger::LoggerPtr LoggerManager::getLogger(const std::string& strName)
{
    MutexType::Lock lock(m_mutex);
    auto it = m_Loggers.find(strName);
    if (it != m_Loggers.end())
    {
        return it->second;
    }

    // log不存在创建一个log并将root赋值
    Logger::LoggerPtr log = std::make_shared<Logger>(strName);
    log->m_Root = m_RootLogger;
    m_Loggers[strName] = log;
    return log;
}

void LoggerManager::Init()
{

}

std::string LoggerManager::toYamlString()
{
    MutexType::Lock lock(m_mutex);
    YAML::Node node;
    for (auto i : m_Loggers)
    {
        node.push_back(YAML::Load(i.second->ToYmalString()));
    }

    std::stringstream ss;
    ss << node;
    return ss.str();
}

struct LogIniter
{
    LogIniter()
    {
        g_log_defines->addListener(0xFFFF8
                , [](const std::set<LogDefine>& old_val, const std::set<LogDefine>& new_val){
                //SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "on_logger_conf_changed";
                for (auto& i : new_val)
                {
                    sylar::Logger::LoggerPtr logger = nullptr;
                    auto it = old_val.find(i);
                    if (it == old_val.end())
                    {   // 新增logger
                        logger = SYLAR_LOG_NAME(i.name);
                    }
                    else
                    {
                        // logger是否变化 修改
                        if( ! (*it == i))
                        {
                            logger = SYLAR_LOG_NAME(i.name);
                        }
                        else
                        {
                            continue;
                        }
                    }

                    logger->SetLogLevel(i.level);
                    if (! i.formatter.empty())
                    {
                        logger->SetFormmat(i.formatter);
                    }

                    logger->CleanAppender();
                    for (auto& a : i.appenders)
                    {
                        sylar::BaseLogAppender::LogAppenderPtr ap;
                        if (a.type == 1)
                        {
                            // std::cout << a.type ;
                            ap.reset(new FileOutLoggAppender(a.file));
                        }
                        else if (a.type == 2)
                        {
                            ap.reset(new StdOutLogAppender());
                        }

                        ap->SetLevel(a.level);
                        if (! a.formatter.empty())
                        {
                            LogFormatter::LogFormatPtr fmt = std::make_shared<LogFormatter>(a.formatter);
                            if (!fmt->IsError())
                            {
                                ap->SetLogFormat(fmt);
                            }
                            else
                            {
                                std::cout << "log.name=" << i.name << " appender type=" << a.type
                                      << " formatter=" << a.formatter << " is invalid" << std::endl;
                            }
                        }
                        logger->AddAppender(ap);
                    }

                }
                 
                // 删除
                for (auto i : old_val)
                {
                    auto it = new_val.find(i);
                    if (it == new_val.end())
                    {
                        auto logger = SYLAR_LOG_NAME(i.name);
                        logger->SetLogLevel((LogLevel::Level)0);
                        logger->CleanAppender();
                    }
                }

        });
    }
};

static LogIniter __log_init;

}



